using System;
using System.Runtime.Serialization;

namespace CosyTrade.Core
{
    [Serializable]
    public class RemotingException : Exception
    {
        private readonly string innerExceptionMessage;
        private readonly string innerExceptionName;
        private readonly string innerExceptionStackTrace;
        private readonly string innerExceptionTargetSite;

        public RemotingException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
            object InnerExceptionNameValue = info.GetValue("InnerExceptionName", typeof (string));
            object InnerExceptionStackTraceValue = info.GetValue("InnerExceptionStackTrace", typeof (string));
            object InnerExceptionMessageValue = info.GetValue("InnerExceptionMessage", typeof (string));
            object InnerExceptionTargetSiteValue = info.GetValue("InnerExceptionTargetSite", typeof (string));

            if (InnerExceptionNameValue != null)
                innerExceptionName = InnerExceptionNameValue.ToString();
            if (InnerExceptionStackTraceValue != null)
                innerExceptionStackTrace = InnerExceptionStackTraceValue.ToString();
            if (InnerExceptionMessageValue != null)
                innerExceptionMessage = InnerExceptionMessageValue.ToString();
            if (InnerExceptionTargetSiteValue != null)
                innerExceptionTargetSite = InnerExceptionTargetSiteValue.ToString();
        }

        public RemotingException(string message, Exception innerException) : base(message, innerException)
        {
        }

        public RemotingException(Exception innerException) : base(innerException.Message)
        {
            Exception sourceException = innerException;
            while (string.IsNullOrEmpty(sourceException.Message) && sourceException.InnerException != null)
                sourceException = sourceException.InnerException;

            if (innerException.TargetSite != null) innerExceptionTargetSite = innerException.TargetSite.ToString();
            innerExceptionMessage = sourceException.Message;
            innerExceptionName = innerException.GetType().Name;
            innerExceptionStackTrace = innerException.StackTrace;
        }

        public RemotingException(string message) : base(message)
        {
        }

        public RemotingException()
        {
        }

        public string InnerExceptionName
        {
            get { return innerExceptionName; }
        }

        public string InnerExceptionStackTrace
        {
            get { return innerExceptionStackTrace; }
        }

        public string InnerExceptionMessage
        {
            get { return innerExceptionMessage; }
        }

        public string InnerExceptionTargetSite
        {
            get { return innerExceptionTargetSite; }
        }

        public override string Message
        {
            get
            {
                if (!string.IsNullOrEmpty(base.Message))
                    return base.Message;
                else return InnerExceptionMessage;
            }
        }

        public override string StackTrace
        {
            get
            {
                if (!string.IsNullOrEmpty(base.StackTrace))
                    return base.StackTrace;
                else return InnerExceptionStackTrace;
            }
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("InnerExceptionName", InnerExceptionName);
            info.AddValue("InnerExceptionStackTrace", innerExceptionStackTrace);
            info.AddValue("InnerExceptionMessage", innerExceptionMessage);
            info.AddValue("InnerExceptionTargetSite", InnerExceptionTargetSite);
        }
    }
}